home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Tool Chest / Development Kits / MPW etc. / Debuggers / SADE / SADE 1.3.3 / SADE Example Scripts / Resource < prev    next >
Encoding:
Text File  |  1991-07-29  |  11.6 KB  |  285 lines  |  [TEXT/sade]

  1. #    Symbolic Application Debugging Environment    1.3 Final
  2. #
  3. #    Copyright Apple Computer, Inc. 1987-1991
  4. #    All rights reserved.
  5.  
  6. ###############################################################################
  7. # --------------------------------------------------------------------------------------
  8. # to TRACE THE RESOURCE CHAIN AND DISPLAY RESOURCE MAP INFORMATION
  9. # select and enter all procs then execute:
  10. # resmap or resmap "rsrc" to see just info for specified resource type (case sensitive)
  11. # --------------------------------------------------------------------------------------
  12.     
  13. proc fileName(FileRefNum)
  14.     define FCBSPTr := $34E                                                                            
  15.     printf ("File Name: %P ", ^pstring (FCBSPtr^ + fileRefNum + 62)^)
  16. end
  17.  
  18.  
  19. proc ResName(nameOffset)
  20.     define resNamePtr    
  21.     ResNamePtr := NEXTresFile + (^Word(NEXTresFile + 26)^)        # get start of  name list
  22.     ResNamePtr := ResNamePtr + nameOffset                        # add offset into list for this resource.
  23.     printf("   name:%P ", ^pstring(resNamePtr)^)                              
  24. end
  25.  
  26.     
  27. proc ResInfo(refListPtr, numThisType)                    
  28.     define looper
  29.     define resId
  30.     define resAttributes
  31.     define resHandle
  32.     define resPtr
  33.     define nameOffset
  34.     
  35.     for looper := 0 to numThisType                                # show info for all resources of current type
  36.         resId := ^Word(refListPtr)^
  37.         printf("\n      ID: % 6d", resId)                        # info for each resource includes: resId
  38.         resHandle := (refListPtr + 8)^
  39.         if resHandle = 0 then                                    # if resource not in memory, say its at 0.
  40.             resPtr := 0                                                
  41.         else
  42.             resPtr := resHandle^                                # else give memory location where resource is loaded,
  43.         end            
  44.         if $80000000 & resPtr then                              # note if "locked" bit set in resource's master pointer
  45.             printf " *"
  46.         else 
  47.             printf "  "
  48.         end
  49.         resPtr := resPtr & $00ffffff              
  50.          printf("   at: %.8X", resPtr)
  51.         resAttributes := ^UnsignedByte(refListPtr + 4)^                        
  52.         printf ("  attribs: %.8b", resAttributes)                # resource  attributes as bit pattern
  53.  
  54.         nameOffset := ^Word(refListPtr+2)^
  55.         if nameOffset <> -1 then                                # one word offset to resource name from top of name list  
  56.             resName(nameOffset)                                    # if no name    offset is -1                        
  57.         end
  58.         refListPtr := refListPtr + 12
  59.     end
  60. end
  61.  
  62.  
  63. proc ResTypes (typeListPtr, targetType)
  64.     define numTypes    := ^Word(TypeListPtr)^
  65.     define numThisType
  66.     define looper
  67.     define thisResPtr
  68.     define refListPtr
  69.     
  70.     printf ("   Number of Resource types: %d\n", numTypes+1)    # number of resource types in current map    
  71.     for looper := 0 to NumTypes
  72.          ThisResPtr := (typeListPtr + 2) + (looper * 8)
  73.         if targetType = 0 || targetType = thisResPtr^ then        # If optional target type spec in call to ResMap
  74.             numThisType := ^Word(thisResPtr + 4)^                # show info only for that type, else show all types
  75.             printf("\n   type: %.4s  instances: %d", thisResPtr^, numThisType+1)
  76.             refListPtr := ^Word(thisResPtr + 6)^+typeListPtr    # find offset into Reference List for type from top of type list.  
  77.             ResInfo(refListPtr, numThisType)                    # get resource info for type.
  78.         end                
  79.     end        
  80. end    
  81.  
  82.  
  83.  
  84. proc ResMap targetType                    
  85.  
  86.     # Global Variables:
  87.     define global NEXTresFile                                    # pointer to top of current resource map
  88.  
  89.     define FileRef                                 
  90.     define typeList                            
  91.     
  92.     if Nargs = 0 then                                             # if optional target resource type not input, then show info for all types
  93.         targetType := 0                                            # else show info for target type only
  94.     end
  95.     NEXTresFile := @topMapHndl
  96.     printf "\nRESOURCE CHAIN - Top to bottom:"
  97.     while (NextResFile^ <> 0)                                    # display each resource map in the chain, starting from the top map
  98.  
  99.         NEXTresFile := NEXTresFile^^                        
  100.         
  101.         IF NEXTresFile = 0
  102.             printf "\nA resource map has been purged--a major problem!\n"
  103.             return
  104.         end
  105.  
  106.         fileRef := ^Word(NEXTresFile+20)^
  107.  
  108.         printf("\n\nResource map at: %.8X   File ref num: %X\n", NEXTresFile, fileRef)
  109.         fileName(fileRef)                                        # get file name
  110.         typeList := ^Word(NEXTresFile + 24)^
  111.  
  112.         ResTypes (NEXTresFile + typeList, targetType)            # get resource type info
  113.         NextresFile := NextresFile+16;
  114.     end                        
  115.     printf "\n"
  116.     undefine NEXTresFile                                        # pointer to top of current resource map
  117.  
  118. end
  119.  
  120.  
  121. ###############################################################################
  122.  
  123. func CheckMP (thisBlockHndl,thisZonePtr)
  124.     # function returns a result code of 1 if NotOk and 0 if all is well.
  125.     # verify that the handle is not NIL,  and that the master pointer is not odd and is located fully within this zone
  126.     # verify that the master pointer to the block in the resource map matches the 
  127.     # master pointer derived from the block's self relative handle    
  128.     define selfHndl
  129.     define endZone
  130.     define notOk := 0                                                    # assume all is well
  131.     
  132.     if thisBlockhndl = 0 then                                         # check handle in resource map for valid value
  133.         "\n## block has an invalid NIL handle"
  134.         notOk := 1
  135.     elseif  thisBlockHndl^ & $01 = 1 then 
  136.         "\n## block has an invalid odd master pointer"
  137.         notOk := 1
  138.     end                                                                    
  139.     endZone := thisZonePtr^^  & $00ffffff                    # yields size of zone trailer block 
  140.     endZone := thisZonePtr^ + endZone                            # pointer to zone trailer block plus its length is address of last byte in zone.    
  141.     if thisBlockHndl < thisZonePtr || thisBlockHndl + 4 > endZone then    
  142.         "\n## block's master pointer falls outside of this zone"
  143.         printf ("zone start %.8x - zone end %.8x - master pointer at %.8x\n",thisZonePtr, endZone, thisBlockHndl)
  144.         notOk := 1
  145.     end                                                                    
  146.     selfHndl := ((thisBlockHndl^ & $00ffffff )- 8 + 4)^    # yields offset from top ThisZonePtr to this block's master pointer
  147.     selfHndl :=  thisZonePtr + selfHndl                         # is location of  MP indicated by this block's self-relative handle
  148.     if selfHndl^ <> thisBlockHndl^ then     
  149.         "\n## block's self relative handle yields a  master pointer which doesn't match the master pointer in the resource map."
  150.         printf("self-relative MP %.8x - resource map MP %.8x   (high bytes intact)",  selfHndl^, thisBlockHndl^)
  151.         notOk := 1
  152.     end
  153.     return notOk
  154. end # func CheckMP
  155.  
  156.  
  157. func BlockInZone(thisBlockHndl, thisZonePtr)
  158.     # function returns a result code of 1 if NotOk and 0 if all is well
  159.     # verify that this block starts in this zone and doesn't extend beyond it
  160.     # also verify that the block size is not 0 or odd
  161.     define endZone
  162.     define blockSize
  163.     define blockStart
  164.     define notOk := 0                                                    # assume will pass all tests                                            
  165.     
  166.     endZone := thisZonePtr^^  & $00ffffff                    # yields size of zone trailer block 
  167.     endZone := thisZoneptr^ + endZone                            # pointer to zone trailer block plus its length is address of last byte in zone.
  168.     blockSize := ((thisBlockHndl^ & $00ffffff) - 8)^ & $00ffffff    #mask MP high byte, backup 8 to block header, mask tag byte        
  169.     if blockSize = 0 then                                             # check block size
  170.         "\n## block has an invalid NIL size"                    
  171.         notOk := 1
  172.     elseif blockSize & $01 =  1 then                            # (if size is zero it can't also be odd so don't bother to check.)
  173.         "\n## block has an invalid odd size"
  174.         notOk := 1
  175.     end
  176.     blockStart := thisBlockHndl^ & $00ffffff                # check block location 
  177.     if blockStart < thisZonePtr || blockStart > endZone then
  178.         if thisZonePtr = TheZone then
  179.             "\n## resource map's handle for this block yields a starting address outside of expected location in TheZone"
  180.         elseif thisZonePtr = SysZone
  181.             "\n## resource map's handle for this block yields a starting address outside of expected location in SysZone"
  182.         else
  183.             "\n##resource map's handle for this block yields a starting address outside of TheZone or SysZone" 
  184.         end
  185.         printf("start zone %.8x - end zone %.8x - block start %.8x\n", thisZonePtr, endZone, blockStart)
  186.         notOk := 1
  187.     elseif blockStart + blockSize > endZone then
  188.         "\n## block's size extends it beyond the end of this heap zone"
  189.         printf("block start %.8x - block size %.8x - end zone %.8x\n", blockStart, blockSize, endZone)
  190.         notOk := 1
  191.     end    
  192.     return notOk
  193. end # proc BlockInZone
  194.  
  195.  
  196. func CheckRes (typeListPtr, thisZone)
  197.     # func returns 1 if notOk and 0 if all is well
  198.     # locates master pointer in resMap for all loaded resources, then checks each MP and resource for validity
  199.     # and prints diagnostic information for the resource if a problem is found
  200.  
  201.     define refListPtr, thisResEntry
  202.     define numTypes, numThisType
  203.     define typeLoop, resLoop
  204.     define resZone, resHndl, resPtr
  205.     define resAttributes, resId, nameOffset
  206.     define notOk 
  207.     
  208.     numTypes := ^Word (TypeListPtr)    ^                    
  209.     for typeLoop := 0 to NumTypes                                        # for each resource type 
  210.          ThisResEntry := typeListPtr + 2 + typeLoop * 8                                
  211.         numThisType := ^Word(thisResEntry + 4)^                    # find how many of this type         
  212.         refListPtr := ^Word(thisResEntry + 6)^                     # and the start of the reference list for this type 
  213.         refListPtr := typeListPtr + refListPtr                
  214.         for resLoop := 0 to numThisType                                
  215.             resHndl := (refListPtr + 8)^                                                                    
  216.             if resHndl = 0 then
  217.                 resPtr := 0
  218.             else
  219.                 resPtr := resHndl^ & $00ffffff                         # get pointer to resource    
  220.             end                                                                        # check only loaded resources
  221.             if resPtr <> 0 then                                                # (a non-zero handle could point to NIL MP if resource was purged)
  222.                 resAttributes := refListPtr + 4                            
  223.                 resAttributes :=  ^Byte (resAttributes)^            # which heap is resource in?
  224.                 if resAttributes & $0040 then                             # if resSysHeap attribute set 
  225.                     resZone := SysZone                                        # then the resource should be in loaded in the System heap.
  226.                 else                                                                     # else it should be loaded in the current App's heap.
  227.                     resZone := TheZone
  228.                 end
  229.                 notOk := BlockInZone(resHndl,resZone)                #     master pointer to resource should be in this heap            
  230.                 notOk := CheckMp(resHndl, thisZone)                    # where this heap is app heap unless resfile is system's
  231.                 if notOk then                                                        # an error was reported
  232.                     resId := ^Word (refListPtr)^                            # give ID and name for the problem resource 
  233.                     printf("\n      ID: % .5d", resId)
  234.                     nameOffset := ^Word(refListPtr+2)^
  235.                     if nameOffset <> -1 then
  236.                         resName(nameOffset)
  237.                     end  
  238.                 end    # notOk        
  239.             end   # resPtr <> 0
  240.             refListPtr := refListPtr + 12                                # move on to test next resource in reference list
  241.         end #  resLoop                                                            # till all resources of this type are tested
  242.     end    # typeLoop                                                            # then test next resource type 
  243.     return notOk
  244. end    # proc CheckRes
  245.  
  246.  
  247. proc ResVerify 
  248.     # verifies all resource maps in the resource chain and all loaded resources (see CheckMP and BlockInZone for details)
  249.     # prints diagnostics if a problem is found
  250.     # reports as an error the case where a resource's attributes indicate it will load in the System heap but 
  251.     # the resource is loaded in the application heap anyway because the System heap doesn't have the space
  252.     # (we might want to get fancy at some point and verify that all offsets calculated for tracing the resource map are
  253.     # still within the map, but i figure if we get there the offsets must have been ok.)
  254.  
  255.     # Global Variables:
  256.     define global NEXTresFile                                                # pointer to top of current resource map
  257.  
  258.     define thisZone
  259.     define FileRef                            
  260.     define typeListOffset
  261.     define nextResHndl := topMapHndl     
  262.     define notOk 
  263.         
  264.     "\nVerifying the Resource Chain:"
  265.     repeat
  266.         NEXTresFile := nextResHndl^                # (this guy is global - for use in ResName, which is called from CheckRes)            
  267.         fileRef := ^Word(NEXTresFile+20)^
  268.         printf("\nResource map at: %.8X   File ref num: %X\n", NEXTresFile, fileRef)
  269.         fileName(fileRef)        
  270.         if fileRef = 2 then                                # System resource map and master pointers should be in the System heap
  271.             thisZone := SysZone                        # all other resource maps and master pointers should be in the current App heap
  272.         else                                                    
  273.             thisZone := TheZone    
  274.         end
  275.         notOk := CheckMp(nextResHndl, thisZone)        
  276.         typeListOffset := ^Word(NEXTresFile + 24)^
  277.         notOk := CheckRes (NEXTresFile + typeListOffset, thisZone)
  278.         if ! notOk then
  279.             "\nlooking good!"
  280.         end
  281.         nextResHndl := (NEXTresFile + 16)^  # check next resource map
  282.     until (nextResHndl = 0)                            # until no more resource maps to check
  283.     undefine NEXTresFile
  284. end    # proc ResVerify
  285.